package com.app.bussinesslocator;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;

import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;

import android.annotation.SuppressLint;
import android.app.Activity;
import android.app.Dialog;
import android.content.Intent;
import android.graphics.Color;
import android.location.Criteria;
import android.location.Location;
import android.location.LocationListener;
import android.location.LocationManager;
import android.os.Bundle;
import android.os.Handler;
import android.text.format.DateUtils;
import android.util.Log;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.AbsListView.OnScrollListener;
import android.widget.AdapterView;
import android.widget.AdapterView.OnItemClickListener;
import android.widget.AbsListView;
import android.widget.Button;
import android.widget.ListView;
import android.widget.ProgressBar;
import android.widget.TextView;
import android.widget.Toast;

import com.app.bussinesslocator.Utils.PreferenceHelper;
import com.app.bussinesslocator.adapter.ResultAdapter;
import com.app.bussinesslocator.bean.ObjBussiness;
import com.app.bussinesslocator.bean.ObjOpenHours;
import com.app.bussinesslocator.httpclient.HttpClientHelper;
import com.app.bussinesslocator.httpclient.MyJsonHttpResponseHandler;
import com.app.bussinesslocator.myUI.PullToRefreshListView;
import com.app.bussinesslocator.myUI.PullToRefreshListView.OnRefreshListener;
import com.google.android.gms.common.ConnectionResult;
import com.google.android.gms.common.GooglePlayServicesUtil;
import com.google.android.gms.maps.CameraUpdateFactory;
import com.google.android.gms.maps.GoogleMap;
import com.google.android.gms.maps.GoogleMap.InfoWindowAdapter;
import com.google.android.gms.maps.GoogleMap.OnMarkerClickListener;
import com.google.android.gms.maps.MapFragment;
import com.google.android.gms.maps.model.BitmapDescriptorFactory;
import com.google.android.gms.maps.model.LatLng;
import com.google.android.gms.maps.model.Marker;
import com.google.android.gms.maps.model.MarkerOptions;

public class FindNearActivity extends Activity implements OnClickListener,
		LocationListener {

	PreferenceHelper preferenceHelper;
	Button btnBack;
	PullToRefreshListView listResult;
	ResultAdapter adapter;
	ArrayList<ObjBussiness> objBussinesses = new ArrayList<ObjBussiness>();

	Button btnDistance, btnPrice, btnRating;

	String type = "distance";

	int mPage = 0;

	private GoogleMap googleMap;
	Location location;
	double mLatitude;
	double mLongitude;
	private ArrayList<ObjBussiness> mMyMarkersArray;
	private HashMap<Marker, ObjBussiness> mMarkersHashMap;

	double mLatObjBus, mLongObjBus;
	private int preLast;
	boolean isLoading = false;
	TextView txtNoResult;
	boolean isCanloadMore = true;
	ProgressBar progressBar;
	TextView title;
	boolean isResume = false;
	Runnable rFind = new Runnable() {

		@Override
		public void run() {
			adapter.clear();
			mPage = 0;
			objBussinesses.clear();
			googleMap.clear();
			findNear(type, mPage);
		}
	};

	Handler mHandler = new Handler();

	Button btnLoadMore;

	@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.activity_find_near);

		preferenceHelper = new PreferenceHelper(this);

		btnBack = (Button) findViewById(R.id.btn_back);
		title = (TextView) findViewById(R.id.title);
		title.setText("Find Nearest");

		listResult = (PullToRefreshListView) findViewById(R.id.list_result);
		btnDistance = (Button) findViewById(R.id.btn_distance);
		btnPrice = (Button) findViewById(R.id.btn_price);
		btnRating = (Button) findViewById(R.id.btn_rating);
		txtNoResult = (TextView) findViewById(R.id.txt_no_result);
		progressBar = (ProgressBar) findViewById(R.id.progressBar);

		// Creating a button - Load More
		btnLoadMore = new Button(this);
		btnLoadMore.setText("Show More");
		btnLoadMore.setTextColor(Color.BLACK);
		btnLoadMore.setBackgroundColor(Color.TRANSPARENT);

		adapter = new ResultAdapter(FindNearActivity.this, objBussinesses);
		listResult.setAdapter(adapter);
		listResult.addFooterView(btnLoadMore);

		btnLoadMore.setOnClickListener(new OnClickListener() {

			@Override
			public void onClick(View v) {
				if (isLoading == false) {
					mPage = mPage + 1;
					btnLoadMore.setText("Loading...");
					findNear(type, mPage);
				}
			}
		});

		mMarkersHashMap = new HashMap<Marker, ObjBussiness>();

		if (isResume == false) {
			findNear(type, mPage);
		}

		init();

		listResult.setOnItemClickListener(new OnItemClickListener() {

			@Override
			public void onItemClick(AdapterView<?> arg0, View v, int position,
					long id) {
				Intent t = new Intent(FindNearActivity.this,
						BussinessPageActivity.class);
				t.putExtra("objBusiness", objBussinesses.get(position - 1));
				t.putExtra("objOpenHour", objBussinesses.get(position - 1)
						.getObjOpenHours());
				startActivity(t);
			}

		});

		listResult.setOnScrollListener(new OnScrollListener() {

			@Override
			public void onScrollStateChanged(AbsListView arg0, int arg1) {
				// TODO Auto-generated method stub

			}

			@Override
			public void onScroll(AbsListView view, int firstVisibleItem,
					int visibleItemCount, int totalItemCount) {
				int lastItem = firstVisibleItem + visibleItemCount;
				if (lastItem == totalItemCount) {
					/*
					 * if (preLast != lastItem) { int last_pos =
					 * listResult.getLastVisiblePosition(); if (last_pos >=
					 * objBussinesses.size() - 1 && !isLoading && isCanloadMore)
					 * { findNear(type, ++mPage); } preLast = lastItem; }
					 */
				}
			}
		});

		/*
		 * listResult.setOnRefreshListener(new OnRefreshListener<ListView>() {
		 * 
		 * @Override public void onRefresh(PullToRefreshBase<ListView>
		 * refreshView) { findNear(type, 0); } });
		 */
		listResult.setOnRefreshListener(new OnRefreshListener() {

			@Override
			public void onRefresh() {
				mHandler.removeCallbacks(rFind);
				mHandler.postDelayed(rFind, 200);
			}
		});

		// Getting status
		int status = GooglePlayServicesUtil
				.isGooglePlayServicesAvailable(getBaseContext());

		// Showing status
		if (status == ConnectionResult.SUCCESS) {
			/*Toast.makeText(FindNearActivity.this,
					"Google Play Services are available", Toast.LENGTH_SHORT)
					.show();*/
			setUpMap();
			focusLocation();

			googleMap.setOnMarkerClickListener(new OnMarkerClickListener() {

				@Override
				public boolean onMarkerClick(Marker marker) {

					// Marker key= (Marker) myVeryOwnIterator.next();

					ObjBussiness value = (ObjBussiness) mMarkersHashMap
							.get(marker);
					Intent t = new Intent(FindNearActivity.this,
							BussinessPageActivity.class);
					t.putExtra("objBusiness", value);
					t.putExtra("objOpenHour", value.getObjOpenHours());
					startActivity(t);
					return false;
				}
			});
		} else {
			Toast.makeText(FindNearActivity.this,
					"Google Play Services are not available",
					Toast.LENGTH_SHORT).show();
			int requestCode = 10;
			Dialog dialog = GooglePlayServicesUtil.getErrorDialog(status, this,
					requestCode);
			dialog.show();
		}

	}

	private void pullToRefresh() {

	}

	void init() {
		btnBack.setOnClickListener(this);
		btnDistance.setOnClickListener(this);
		btnPrice.setOnClickListener(this);
		btnRating.setOnClickListener(this);
	}

	@Override
	public void onClick(View v) {
		switch (v.getId()) {
		case R.id.btn_back:
			finish();
			break;
		case R.id.btn_distance:
			if (type.equals("distance")) {

			} else {

				progressBar.setVisibility(View.VISIBLE);
				btnDistance.setTextColor(getResources().getColor(
						R.color.color_red));
				btnPrice.setTextColor(getResources().getColor(
						R.color.color_black));
				btnRating.setTextColor(getResources().getColor(
						R.color.color_black));
				mPage = 0;
				adapter.clear();
				type = "distance";
				objBussinesses.clear();
				googleMap.clear();
				findNear(type, mPage);
			}
			break;
		case R.id.btn_price:
			if (type.equals("price")) {

			} else {
				progressBar.setVisibility(View.VISIBLE);
				btnDistance.setTextColor(getResources().getColor(
						R.color.color_black));
				btnPrice.setTextColor(getResources()
						.getColor(R.color.color_red));
				btnRating.setTextColor(getResources().getColor(
						R.color.color_black));
				mPage = 0;
				adapter.clear();
				objBussinesses.clear();
				type = "price";
				googleMap.clear();
				findNear(type, mPage);
			}
			break;
		case R.id.btn_rating:
			if (type.equals("rating")) {

			} else {
				progressBar.setVisibility(View.VISIBLE);
				btnDistance.setTextColor(getResources().getColor(
						R.color.color_black));
				btnPrice.setTextColor(getResources().getColor(
						R.color.color_black));
				btnRating.setTextColor(getResources().getColor(
						R.color.color_red));
				mPage = 0;
				adapter.clear();
				objBussinesses.clear();
				type = "rating";
				googleMap.clear();
				findNear(type, mPage);
			}
			break;

		default:
			break;
		}
	}

	void findNear(String type, final int page) {
		isLoading = true;
		HttpClientHelper httpClientHelper = new HttpClientHelper(
				new MyJsonHttpResponseHandler() {

					@Override
					public void onFailure(Throwable error) {
						super.onFailure(error);
						isLoading = false;
						btnLoadMore.setText("Show More");
					}

					@Override
					public void onSuccess(JSONObject re) {
						super.onSuccess(re);
						Log.i("DATA", "TO NHAT: " + re.toString());
						try {
							int status = re.getInt("status");
							isLoading = false;
							progressBar.setVisibility(View.GONE);
							btnLoadMore.setText("Show More");
							if (status == 200) {
								// adapter.clear();
								JSONArray ja = re.getJSONArray("data");
								Log.i("DODAI", "DO DAI TRA VE: " + ja.length());
								if (ja.length() < 5) {
									// isCanloadMore = false;
									btnLoadMore.setVisibility(View.GONE);
								} else {
									btnLoadMore.setVisibility(View.VISIBLE);
								}

								if (ja.length() == 0) {
									txtNoResult.setVisibility(View.VISIBLE);
									return;
								} else {
									txtNoResult.setVisibility(View.GONE);
								}

								if (page == 0) {
									adapter.clear();
								}
								mMyMarkersArray = new ArrayList<ObjBussiness>();
								for (int i = 0; i < ja.length(); i++) {
									JSONObject data = ja.getJSONObject(i);
									// check data rong tai day
									Log.i("DATA",
											"DATA BUSSINESS: "
													+ data.toString());
									String bussinessName = data
											.getString("business_name");
									String address = data.getString("address");
									float longitude = (float) data
											.getDouble("longitude");
									float latitude = (float) data
											.getDouble("latitude");
									int rating1 = data.getInt("bread");
									int rating2 = data.getInt("meat");
									int rating3 = data.getInt("filling");
									int rating4 = data.getInt("condiments");
									float overall = (float) data
											.getDouble("overall");
									String price = data.getString("price");
									float distance = (float) data
											.getDouble("distance");

									ArrayList<ObjOpenHours> objOpenHours = new ArrayList<ObjOpenHours>();
									JSONObject openHours = data
											.getJSONObject("open_hours");
									Iterator<String> keys = openHours.keys();
									JSONArray mt = new JSONArray();
									while (keys.hasNext()) {
										String key = keys.next();
										String value = openHours.optString(key);
										// add value to JSONArray from
										// JSONObject
										mt.put(value);
										ObjOpenHours objOpenHour = new ObjOpenHours();
										objOpenHour.setThuNgay(key);
										objOpenHour.setThoigianMocua(value);
										objOpenHours.add(objOpenHour);
										Log.i("DATA", "" + key + " " + ""
												+ value);
									}

									ObjBussiness objBussiness = new ObjBussiness();

									objBussiness
											.setBussinessName(bussinessName);
									objBussiness.setAddress(address);
									objBussiness.setLongitude(longitude);
									objBussiness.setLatitude(latitude);
									objBussiness.setRating1(rating1);
									objBussiness.setRating2(rating2);
									objBussiness.setRating3(rating3);
									objBussiness.setRating4(rating4);
									objBussiness.setOverall(overall);
									objBussiness.setDistance(distance);
									objBussiness.setPrice(price);
									objBussiness.setObjOpenHours(objOpenHours);

									mLatObjBus = latitude;
									mLongitude = longitude;

									objBussinesses.add(objBussiness);

									mMyMarkersArray.add(objBussiness);
								}
								adapter.notifyDataSetChanged();
								listResult.onRefreshComplete();
								plotMarkers(mMyMarkersArray);

							}
						} catch (JSONException e) {
							e.printStackTrace();
						}
					}

				});
		httpClientHelper.searchNear(type, page, preferenceHelper.getLON(),
				preferenceHelper.getLAT());
	}

	@Override
	protected void onResume() {
		super.onResume();

		focusLocation();

		if (isResume == true) {
			findNear(type, 0);
		}
		Log.i("DATA", "ON RESUME");
	}

	@Override
	protected void onPause() {
		super.onPause();
		Log.i("DATA", "ON PAUSE");
		isResume = true;
	}

	@Override
	protected void onStart() {
		super.onStart();
		Log.i("DATA", "ON START");
	}

	@SuppressLint("NewApi")
	private void setUpMap() {
		// Do a null check to confirm that we have not already instantiated the
		// map.
		if (googleMap == null) {
			// Try to obtain the map from the SupportMapFragment.
			googleMap = ((MapFragment) getFragmentManager().findFragmentById(
					R.id.map)).getMap();

			// Check if we were successful in obtaining the map.

			// Enabling MyLocation in Google Map
			googleMap.setMyLocationEnabled(true);
			googleMap.getUiSettings().setMyLocationButtonEnabled(true);

			/*
			 * // Creating an instance of MarkerOptions MarkerOptions
			 * markerOptions = new MarkerOptions();
			 * 
			 * // Setting position for the marker markerOptions.position(new
			 * LatLng(mLatitude, mLongitude));
			 * 
			 * // Setting custom icon for the marker
			 * markerOptions.icon(BitmapDescriptorFactory
			 * .fromResource(R.drawable.my_location));
			 * 
			 * // Adding the marker to the map
			 * googleMap.addMarker(markerOptions);
			 * 
			 * googleMap.setOnMarkerClickListener(new OnMarkerClickListener() {
			 * 
			 * @Override public boolean onMarkerClick(Marker marker) { return
			 * false; } });
			 */
			// Getting LocationManager object from System Service
			// LOCATION_SERVICE
			LocationManager locationManager = (LocationManager) getSystemService(LOCATION_SERVICE);

			// Creating a criteria object to retrieve provider
			Criteria criteria = new Criteria();

			// Getting the name of the best provider
			String provider = locationManager.getBestProvider(criteria, true);

			// Getting Current Location From GPS

			location = locationManager.getLastKnownLocation(provider);

			if (location != null) {
				onLocationChanged(location);
			}

			locationManager.requestLocationUpdates(provider, 20000, 0,
					new android.location.LocationListener() {

						@Override
						public void onStatusChanged(String provider,
								int status, Bundle extras) {
							// TODO Auto-generated method stub

						}

						@Override
						public void onProviderEnabled(String provider) {
							// TODO Auto-generated method stub

						}

						@Override
						public void onProviderDisabled(String provider) {
							// TODO Auto-generated method stub

						}

						@Override
						public void onLocationChanged(Location location) {
							// TODO Auto-generated method stub
							/*
							 * mLatitude = (float) location.getLatitude();
							 * mLongitude = (float) location.getLongitude();
							 * LatLng latLng = new LatLng(mLatitude,
							 * mLongitude);
							 * 
							 * Log.i("DATA", "LAT: " + mLatitude + "LONG: " +
							 * mLongitude);
							 * 
							 * googleMap.moveCamera(CameraUpdateFactory
							 * .newLatLng(latLng));
							 * googleMap.animateCamera(CameraUpdateFactory
							 * .zoomTo(12));
							 */
						}
					});
		}

		googleMap.setInfoWindowAdapter(new InfoWindowAdapter() {

			@Override
			public View getInfoWindow(Marker marker) {
				return null;
			}

			@Override
			public View getInfoContents(Marker marker) {
				return null;
			}
		});

	}

	void focusLocation() {
		try {
			mLatitude = (float) location.getLatitude();
			mLongitude = (float) location.getLongitude();
			LatLng latLng = new LatLng(mLatitude, mLongitude);

			Log.i("DATA", "LAT: " + mLatitude + "LONG: " + mLongitude);

			googleMap.moveCamera(CameraUpdateFactory.newLatLng(latLng));
			googleMap.animateCamera(CameraUpdateFactory.zoomTo(10));
		} catch (Exception e) {
			e.printStackTrace();
		}
	}

	@Override
	public void onLocationChanged(Location arg0) {
		// TODO Auto-generated method stub

	}

	@Override
	public void onProviderDisabled(String arg0) {
		// TODO Auto-generated method stub

	}

	@Override
	public void onProviderEnabled(String arg0) {
		// TODO Auto-generated method stub

	}

	@Override
	public void onStatusChanged(String arg0, int arg1, Bundle arg2) {
		// TODO Auto-generated method stub

	}

	private void plotMarkers(ArrayList<ObjBussiness> markers) {
		if (markers.size() > 0) {
			for (ObjBussiness objBussiness : markers) {

				// Create user marker with custom icon and other options
				MarkerOptions markerOption = new MarkerOptions()
						.position(new LatLng(objBussiness.getLatitude(),
								objBussiness.getLongitude()));
				markerOption.icon(BitmapDescriptorFactory
						.fromResource(R.drawable.problem));

				Marker currentMarker = googleMap.addMarker(markerOption);
				mMarkersHashMap.put(currentMarker, objBussiness);

			}
		}
	}

}
